﻿using HtmlAgilityPack;
using ScrapperBase;
using SoccerGameSpider.DataContext;
using SoccerGameSpider.Entities;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
using System.Configuration;
using System.Linq;
using System.Data.Entity;

namespace SoccerGameSpider.Scraper
{
    public class FranceScraper : ScraperBase
    {
        private const int RoundCount = 38;

        private const string MatchUrl = @"http://www.foot-national.com/{0}-{1}-calendrier-ligue{2}-{3}.html";

        private readonly DateTime startDate = new DateTime(2008, 8, 6);

        protected override Country Country
        {
            get { return ScrapperBase.Country.France; }
        }

        protected override int CurrentYear
        {
            get {
                return DateTime.Now.Month >= 7 ? DateTime.Now.Year : DateTime.Now.Year - 1; 
            }
        }

        protected override int StartYear
        {
            get { return 2008; }
        }

        private GameContext db = GameContext.Db;

        protected override void Scrape(League league, int year)
        {
            Trace.TraceInformation("Start the year {0}", year);

            var yearMatches = league.Matches.Where(m => m.MatchTime.Year == year).ToList();
            int maxRound = yearMatches.Count() > 0 ? yearMatches.Max(m => m.Round) : 0;
            int round = maxRound + 1;

            while (round <= RoundCount)
            {
                Trace.TraceInformation("Start the round {0}", round);

                this.Scrape(league, year, round);

                Trace.TraceInformation("Save the changes to db");
                db.SaveChanges();

                round += 1;
            }
        }

        private void Scrape(League league, int year, int round)
        {
            string url = string.Format(MatchUrl, year, year + 1, league.Id, round);

            WebClient webClient = new WebClient();
            byte[] buffer = webClient.DownloadData(url);
            MemoryStream stream = new MemoryStream(buffer);

            HtmlDocument mainDoc = new HtmlDocument();
            mainDoc.Load(stream, Encoding.GetEncoding("ISO-8859-1"));

            this.Scrape(league, mainDoc, round);
        }

        private void Scrape(League league, HtmlDocument doc, int round)
        {
            HtmlNode matchesNode = doc.DocumentNode.SelectSingleNode("//div[@id='calendrier']/table");

            if (matchesNode == null)
            {
                //Todo: log 'there is no match table found in this document
                return;
            }

            if ((matchesNode.InnerText.IndexOf("RÉSUMÉ") == -1 && matchesNode.InnerText.IndexOf("PARIEZ") == -1))
            {
                //Todo: log there is no match detail link in this table
                return;
            }

            HtmlNodeCollection rows = matchesNode.SelectNodes(".//tr");

            if (rows.Count == 0)
            {
                //Todo: log there is no match rows found in this table.
                return;
            }

            DateTime matchDate = DateTime.MaxValue;

            foreach (HtmlNode row in rows)
            {
                //when the tag is "th", it's match date line
                if (row.FirstChild.Name == "th")
                {
                    string dateText = row.InnerText;
                    DateTime.TryParse(dateText, CultureInfo.GetCultureInfo("fr-Fr"), DateTimeStyles.None, out matchDate);
                    continue;
                }

                Debug.WriteLine(row.InnerText);

                var match = this.CreateMatch(league, matchDate, row);
                match.Round = round;

                FranceMatchLoader loader = new FranceMatchLoader();
                loader.LoadDetail(match);

                league.Matches.Add(match);

                //db.Matches.Add(match);
            }
        }

        private Match CreateMatch(League league, DateTime matchDate, HtmlNode row)
        {
            Match match = new Match();
            DateTime time = GetTimeFromRow(row);

            match.MatchTime = matchDate.AddHours(time.Hour);

            Trace.TraceInformation("Scrape the match at {0}", match.MatchTime);

            string homeName = row.SelectSingleNode("./td[@class='t1']").InnerText;
            match.HomeTeam = league.GetTeam(homeName);

            string awayName = row.SelectSingleNode("./td[@class='t3']").InnerText;
            match.AwayTeam = league.GetTeam(awayName);

            int homeScore, awayScore;

            GetScoresFromRow(row, out homeScore, out awayScore);

            match.HomeScore = homeScore;
            match.AwayScore = awayScore;

            match.DetailUrl = row.SelectSingleNode("./td[@class='t4']/a").GetAttributeValue("href", string.Empty);
            match.League = league;

            return match;
        }

        private static DateTime GetTimeFromRow(HtmlNode row)
        {
            string timeText = row.SelectSingleNode("./td[@class='t0']").InnerText;

            DateTime time = DateTime.MaxValue;

            DateTime.TryParse(timeText, CultureInfo.GetCultureInfo("fr-Fr"), DateTimeStyles.None, out time);
            return time;
        }

        private static void GetScoresFromRow(HtmlNode row, out int homeScore, out int awayScore)
        {
            string score = row.SelectSingleNode("./td[@class='t2']").InnerText;
            string[] homeAway = score.Split('-');
            homeScore = int.Parse(homeAway[0].Trim());
            awayScore = int.Parse(homeAway[1].Trim());
        }
    }
}
